/*  -*- mode: c++; coding: utf-8; c-file-style: "stroustrup"; -*-

    Copyright 2008 Asier Aguirre <asier.aguirre@gmail.com>
    This file is part of Intromit.

    Intromit is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Intromit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Intromit.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "render_stats.hh"

#include <string.h>
#include <sys/time.h>

// CONSTANTS
static const char *render_stats_str[RS_LAST+1]=
{
    "# PASS",
    "TIME[ms]",
    "MAX[ms]",
    "MEAN[ms]",
    "ACCU[ms]",
    "LAST OBJ",
    "MAX OBJ",
    "MEAN OBJ",
    "TOT. OBJ",
    "",
};

CLASS_INIT(render_stats); // RENDER_STATS CLASS

render_stats::render_stats()
{
    CLASS_CTOR(render_stats);
    ctor();
}

render_stats::~render_stats()
{
    CLASS_DTOR(render_stats);
    dtor();
}

void render_stats::ctor()
{
    reset();
    stats_type=RS_N_PASS;
}

void render_stats::dtor()
{
}

bool render_stats::init()
{
    for(int i=0; i<RENDER_PASS_LAST_ALL; i++)
    {
	passv[i].render_init=0;
	passv[i].time_start=0;
    }
    return true;
}

void render_stats::reset()
{
    for(int i=0; i<RENDER_PASS_LAST_ALL; i++)
    {
	passv[i].n=0;
	passv[i].render_init_max=0;
	passv[i].render_init_accum=0;
	passv[i].time=0;
	passv[i].time_max=0;
	passv[i].time_accum=0;
    }
}

void render_stats::reset_render_init(render_pass p)
{
    // max
    if(passv[p].render_init>passv[p].render_init_max) passv[p].render_init_max=passv[p].render_init;

    // accum
    passv[p].render_init_accum+=passv[p].render_init;

    // reset
    passv[p].render_init=0;
}

void render_stats::clock(render_pass p)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    passv[p].time_start=tv.tv_usec;
}

void render_stats::clock_stop(render_pass p)
{
    // take time
    struct timeval tv;
    gettimeofday(&tv, NULL);
    if((passv[p].time_start=tv.tv_usec-passv[p].time_start)>=IS_USEC_SEC)
	passv[p].time_start+=IS_USEC_SEC;
    passv[p].time=passv[p].time_start*1e-3;

    // max
    if(passv[p].time>passv[p].time_max) passv[p].time_max=passv[p].time;

    // accum
    passv[p].time_accum+=passv[p].time;
}

void render_stats::inc_stats_type()
{
    stats_type=(render_stats_type)((int)stats_type+1);
    if(stats_type==RS_LAST) stats_type=RS_N_PASS;
}

void render_stats::dec_stats_type()
{
    if(stats_type==RS_N_PASS) stats_type=RS_LAST;
    stats_type=(render_stats_type)((int)stats_type-1);
}

char *render_stats::get_current_stat(render_pass p, char buffer[RS_MAX_BUFFER])
{
    switch(stats_type)
    {
    case RS_N_PASS:
	snprintf(buffer, RS_MAX_BUFFER, "%u", passv[p].n);
	break;
    case RS_TIME_LAST:
	snprintf(buffer, RS_MAX_BUFFER, "%.3f", passv[p].time);
	break;
    case RS_TIME_MAX:
	snprintf(buffer, RS_MAX_BUFFER, "%.3f", passv[p].time_max);
	break;
    case RS_TIME_MEAN:
	snprintf(buffer, RS_MAX_BUFFER, "%.3f", passv[p].time_accum/(double)passv[p].n);
	break;
    case RS_TIME_ACCUM:
	snprintf(buffer, RS_MAX_BUFFER, "%.0f", passv[p].time_accum);
	break;
    case RS_OBJ_LAST:
	snprintf(buffer, RS_MAX_BUFFER, "%u", passv[p].render_init);
	break;
    case RS_OBJ_MAX:
	snprintf(buffer, RS_MAX_BUFFER, "%u", passv[p].render_init_max);
	break;
    case RS_OBJ_MEAN:
	snprintf(buffer, RS_MAX_BUFFER, "%.2f", (float)passv[p].render_init_accum/(float)passv[p].n);
	break;
    case RS_OBJ_ACCUM:
	snprintf(buffer, RS_MAX_BUFFER, "%.1fK", (float)passv[p].render_init_accum*1e-3);
	break;
    default:
	*buffer=0;
    }
    return buffer;
}

const char *render_stats::get_current_stat_str()
{
    return render_stats_str[stats_type];
}
